package orxatas.travelme.manager;

import orxatas.travelme.activity.AsyncActivity;
import orxatas.travelme.databases.exceptions.PlaceNotInLocal;
import orxatas.travelme.entity.Geopoint;
import orxatas.travelme.entity.Place;
import orxatas.travelme.entity.PlaceType;
import orxatas.travelme.sync.AsyncNoticeCode;
import orxatas.travelme.sync.SyncPlaces;
import orxatas.travelme.sync.TroovelSearch;
import orxatas.travelme.sync.TroovelSearch.BasicPlace;
import orxatas.travelme.sync.exceptions.ImposibleFindNearPlaces;
import orxatas.travelme.sync.exceptions.ImposibleFindPlaceByName;
import orxatas.travelme.sync.exceptions.ImposibleGetThisLocationAsPlace;


import java.util.ArrayList;

import android.os.AsyncTask;

public class PlaceManager {
	/**
	 * Actividad actual.
	 * */
	private AsyncActivity asyncActivity;
	
	private SyncPlaces syncPlaces;
	
	private class SyncGetThisLocationCall extends AsyncTask<Void, Void, Boolean>{
		
		private final Geopoint point;
		private final int syncAction;
		private ArrayList<TroovelSearch.My_location> list = null;
		
		SyncGetThisLocationCall(Geopoint point, int syncAction){
			this.point = point;
			this.syncAction = syncAction;
		}

		@Override
		protected void onPostExecute(Boolean result) {
			super.onPostExecute(result);
			
			asyncActivity.syncAndWaitCallEnded(list, syncAction);
		}

		@Override
		protected void onPreExecute() {
			asyncActivity.syncAndWaitCallStarted();
		}

		@Override
		protected Boolean doInBackground(Void... params) {
			try {
				list = syncPlaces.getThisLocation(point);
			} catch (ImposibleGetThisLocationAsPlace e) {
				return false;
			}
			if(list == null)
				return false;
			else return true;
		}		
	}
	private class SyncFindPlaceCall extends AsyncTask<Void, Void, Boolean>{
		
		private final String place;
		private final int syncAction;
		private final PlaceType[] types;
		private final int enclosingPlace;
		private ArrayList<BasicPlace> list = null;
		
		SyncFindPlaceCall(String place, PlaceType[] types, int enclosingPlace ,int syncAction){
			this.place = place;
			this.types = types;
			this.enclosingPlace = enclosingPlace;
			this.syncAction = syncAction;
		}

		@Override
		protected void onPostExecute(Boolean result) {
			super.onPostExecute(result);
			
			asyncActivity.syncAndWaitCallEnded(list, syncAction);
		}

		@Override
		protected void onPreExecute() {
			asyncActivity.syncAndWaitCallStarted();
		}

		@Override
		protected Boolean doInBackground(Void... params) {
				try {
					list = syncPlaces.findPlace(place, types, enclosingPlace);
				} catch (ImposibleFindPlaceByName e) {
					return false;
				}
			if(list == null)
				return false;
			else return true;
		}		
	}
	private class SyncSearchNearCall extends AsyncTask<Void, Void, Boolean>{
		
		private final Geopoint point;
		private final int syncAction;
		private final PlaceType[] types;
		private final int enclosingPlace;
		private ArrayList<BasicPlace> list = null;
		
		SyncSearchNearCall(Geopoint point, PlaceType[] types, int enclosingPlace ,int syncAction){
			this.point = point;
			this.types = types;
			this.enclosingPlace = enclosingPlace;
			this.syncAction = syncAction;
		}

		@Override
		protected void onPostExecute(Boolean result) {
			super.onPostExecute(result);
			
			asyncActivity.syncAndWaitCallEnded(list, syncAction);
		}

		@Override
		protected void onPreExecute() {
			asyncActivity.syncAndWaitCallStarted();
		}

		@Override
		protected Boolean doInBackground(Void... params) {
				try {
					list = syncPlaces.searchNear(point, types, enclosingPlace);
				} catch (ImposibleFindNearPlaces e) {
					return false;
				}
			if(list == null)
				return false;
			else return true;
		}		
	}
	public PlaceManager(AsyncActivity asyncActivity){
		this.asyncActivity = asyncActivity;
		
		syncPlaces = new SyncPlaces(this, asyncActivity);		
	}
	public Place getPlace(int idPlace) throws PlaceNotInLocal{
		
		return syncPlaces.getPlace(idPlace);
	}

	public void getThisLocation(Geopoint coordinate, int syncAction){
		
		new SyncGetThisLocationCall(coordinate, syncAction).execute();
	}
	
	public void findPlace(String searchName, PlaceType [] placeType, int enclosingPlace, int syncAction){
		
 		new SyncFindPlaceCall(searchName, placeType, enclosingPlace, syncAction).execute();

	}
	
	public void searchNear(Geopoint coordinate, PlaceType [] placeType, Integer enclosingPlace, int syncAction){
		
		new SyncSearchNearCall(coordinate, placeType, enclosingPlace, syncAction).execute();
	}
	
	/**
	 * Se le avisa de que hay una sincronización en curso. Convenio: Sólo utilizar cuando por su clase de sincronización.
	 * */
	public void syncInProgress(){

		asyncActivity.syncStarted();
	}
	
	/**
	 * Se le avisa de que la sincronización en curso ha terminado. Convenio: Sólo utilizar cuando por su clase de sincronización.
	 * */
	public void syncInProgressEnd(){
		
		asyncActivity.syncEnded();
	}
	/**
	 * Evento asyncrono para cambios en los grupos.
	 * */
	public void asyncNotice(AsyncNoticeCode code){
		
		asyncActivity.asyncNotice(code);
	}
}

